package sonia.drools.test;

import java.util.HashSet;
import java.util.Set;

import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderErrors;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.io.ResourceFactory;
import org.drools.runtime.StatefulKnowledgeSession;

public abstract class DroolsTester {

	private Set<String> drls;
	private Set<String> dsls;
	private Set<String> dsrls;
	private StatefulKnowledgeSession session;

	public Set<String> getDrls() {
		return drls;
	}

	public Set<String> getDsls() {
		return dsls;
	}

	public Set<String> getDsrls() {
		return dsrls;
	}

	public void addDsl(String... dsl) {
		add(getDsls(), dsl);
	}

	public void addDrl(String... drl) {
		add(getDrls(), drl);
	}

	public void addDsrls(String... dsrl) {
		add(getDsrls(), dsrl);
	}

	private void add(Set<String> set, String[] arr) {
		for (int i = 0; i < arr.length; i++) {
			set.add(arr[i]);
		}
	}

	public DroolsTester() {
		drls = new HashSet<String>();
		dsls = new HashSet<String>();
		dsrls = new HashSet<String>();
	}

	protected StatefulKnowledgeSession getSession(){
		if (session == null){
			KnowledgeBase kbase = createKnowledgeBase();
			session = kbase.newStatefulKnowledgeSession();
		}
		return session;
	}
	
	protected KnowledgeBase createKnowledgeBase() {

		KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();

		// 1st add all dsls
		for (String string : getDsls()) {
			kbuilder.add(ResourceFactory.newClassPathResource(string), ResourceType.DSL);
		}

		// 2, add drl
		for (String string : getDrls()) {
			kbuilder.add(ResourceFactory.newClassPathResource(string), ResourceType.DRL);
		}

		// 2, add drl
		for (String string : getDsrls()) {
			kbuilder.add(ResourceFactory.newClassPathResource(string), ResourceType.DSLR);
		}

		KnowledgeBuilderErrors errors = kbuilder.getErrors();
		if (errors.size() > 0) {
			for (KnowledgeBuilderError error : errors) {
				System.err.println(error);
			}
			// todo: if users' files are illegal, use only system files to
			// create layout
			throw new IllegalArgumentException("Could not parse knowledge.");
		}
		
		KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
		kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
		return kbase;
	}
	
	public void test(){
		// 1. create session
		addRules();
		// 1. create session
		getSession();
		// 2. add facts
		addFacts();
		
		// 3.0 preliminary
		preRun();
		// 3. run
		getSession().fireAllRules();
		
		// 4. post run
		postRun();
	}

	protected abstract void postRun();
	protected abstract void preRun();
	protected abstract void addFacts();
	protected abstract void addRules();
}
